using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;

namespace SmallMvc
{
    public class SmallViewEngine : IViewEngine
    {
        private readonly IDictionary<ViewKey, Type> _views = new Dictionary<ViewKey, Type>();

        public void RegisterView<T>(string controllerName, string actionName) where T : SmallView
        {
            _views[new ViewKey(controllerName, actionName)] = typeof(T);
        }

        private void RegisterView(ViewKey viewKey, Type viewType)
        {
            _views[viewKey] = viewType;
        }

        public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            throw new NotImplementedException();
        }

        public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            var routeData = controllerContext.RouteData;
            var controllerName = GetStringFromRouteData(routeData, "Controller");
            var controllerAction = GetStringFromRouteData(routeData, "Action");
            var key = new ViewKey(controllerName, controllerAction);
            if (!_views.ContainsKey(key))
            {
                var message = string.Format("No view registered for controller \"{0}\" and action \"{1}\".",
                                            controllerName, controllerAction);
                throw new Exception(message);
            }
            var type = _views[key];
            var view = (SmallView) Activator.CreateInstance(type);
            return new ViewEngineResult(view, this);
        }

        private string GetStringFromRouteData(RouteData routeData, string key)
        {
            object obj;
            routeData.Values.TryGetValue(key, out obj);
            return obj as string;
        }

        public void ReleaseView(ControllerContext controllerContext, IView view)
        {
        }

        public void RegisterViews(IEnumerable<Type> viewTypes, Func<Type, ViewKey> func)
        {
            foreach (var viewType in viewTypes)
            {
                var viewKey = func(viewType);
                RegisterView(viewKey, viewType);
            }
        }
    }
}